//
// Created by ta&to on 2022/9/28.
//

#include "tcp_connect.h"
#if defined(SOCKET_SERVER_POLL) && !defined(PLATFORM_WINDOWS)
#include <poll.h>

#define POLLMSG	0x400
#define POLLREMOVE	0x1000
#define POLLRDHUP	0x2000

void _init_poll(log_t *logt, struct tcp_socket_event_loop_s *hset) {
    hset->poll_fds = (struct pollfd*)tcp_calloc(sizeof(struct pollfd) * hset->maxfd);
    hset->func_handler->data = (char*) tcp_calloc(hset->func_handler->data_len);
    hset->func_handler->sin_size = sizeof(hset->func_handler->client_addr);
    assert(NULL != hset->poll_fds);
}
// 初始化fds结构体数组
void _create_poll(log_t *logt, struct tcp_socket_event_loop_s *hset)
{
    int i = 0;
    for(; i < hset->maxfd; ++i)
    {
        hset->poll_fds[i].fd = -1;
        hset->poll_fds[i].events = 0;
        hset->poll_fds[i].revents = 0;
    }
}

// 向fds结构体数组中插入一个文件描述符
void _add_fd(log_t *logt, struct tcp_socket_event_loop_s *hset, int fd, int flag)//此处flag是为了判断是文件描述符c，还是listenfd，来设置events
{
    int i = 0;
    for(; i < hset->maxfd; ++i)
    {
        if(hset->poll_fds[i].fd == -1)
        {
            hset->poll_fds[i].fd = fd;
            hset->poll_fds[i].events |= POLLIN;
            if(flag)
            {
                hset->poll_fds[i].events |= POLLRDHUP;
            }
            break;
        }
    }
}

// 从fds结构体数组中删除一个文件描述符
int __monitor_rm_fd(log_t *logt, struct tcp_socket_event_loop_s *hset, int fd)
{
    int i = 0;
    for(; i < hset->maxfd; ++i)
    {
        if(hset->poll_fds[i].fd == fd)
        {
            hset->poll_fds[i].fd = -1;
            hset->poll_fds[i].events = 0;
            break;
        }
    }
    return fd;
}

// 断开一个用户连接
void _offline_client(log_t *logt, struct tcp_socket_event_loop_s *hset, int fd)
{
    info(logt, "A Clien is close[%d]", fd);
    close(fd);              // 关闭描述符
}

void Close_Client(log_t *logt, struct tcp_socket_event_loop_s *hset, int fd) {
    _offline_client(logt, hset, fd);
}
void Close_link(log_t *logt, struct tcp_socket_event_loop_s *hset, int fd) {
    info(logt, "A Clien is close[%d]", fd);
    __monitor_rm_fd(logt, hset, fd);
    close(fd);              // 关闭描述符
}
// 处理客户端发送来的数据
void _fd_handler(log_t *logt, struct tcp_socket_event_loop_s *hset, int fd)
{
    hset->current_fd = fd;
    assert(hset->func_handler);
    hset->func_handler->fd = fd;
    hset->func_handler->func_read(hset, __monitor_rm_fd(logt, hset, fd));
}

// 获取一个已完成三次握手的连接
void _conn_handler(log_t *logt, struct tcp_socket_event_loop_s *hset, int _socket_fd)
{
    int client_fd = Accept(logt, _socket_fd, (struct sockaddr *)&hset->func_handler->client_addr,&hset->func_handler->sin_size);
    assert(client_fd != -1);
    info(logt, "one client link success[%d]", client_fd);
    _add_fd(logt, hset, client_fd, 1);
}

// poll返回后，处理就绪的文件描述符
void _poll_loop(log_t *logt, struct tcp_socket_event_loop_s *hset, int listenfd)
{
    int i = 0;
    for(; i < hset->maxfd; ++i)
    {
        if(hset->poll_fds[i].fd == -1)
            continue;

        int fd = hset->poll_fds[i].fd;
        if(fd == listenfd && hset->poll_fds[i].revents & POLLIN)
            _conn_handler(logt, hset, fd);
        else if(hset->poll_fds[i].revents & POLLRDHUP) {
            debug(logt, "client[%d] be going to close\n", fd);
            _offline_client(logt, hset, fd);
        }
        else if(hset->poll_fds[i].revents & POLLIN)
            _fd_handler(logt, hset, fd);
    }
}
void Poll_do(log_t *logt, struct tcp_socket_event_loop_s *hset) {
    _create_poll(logt, hset);
    _add_fd(logt, hset, hset->socket_fd, 0);
    //插入套接字文件描述符
    while(1)
    {
        int n = poll(hset->poll_fds, hset->maxfd, -1); // 设置poll
        if(n <= 0)
        {
            error(logt, "poll error\n");
            continue;
        }
        _poll_loop(logt, hset, hset->socket_fd);
    }
}
#endif
#if defined(SOCKET_SERVER_POLL)
int Poll(log_t *logt, struct tcp_socket_event_loop_s *hset) {
#ifdef PLATFORM_WINDOWS
    error(logt, "Windows Platform no Support Poll");
#else
    _init_poll(logt, hset);

    Poll_do(logt, hset);
    free( hset->poll_fds );
#endif
}
#endif
